home *** CD-ROM | disk | FTP | other *** search
Text File | 1996-10-20 | 5.7 KB | 198 lines | [TEXT/CWIE] |
- unit MyReferences;
-
- interface
-
- const
- nil_reference = 0;
-
- type
- ReferenceID = longint;
- ReferenceData = longint;
-
- procedure StartupReferences;
-
- procedure MakeNewReference(var ref:ReferenceID; data:univ ReferenceData);
- function GetReferenceInfo(ref:ReferenceID; var data:univ ReferenceData):Boolean;
- procedure GetReferenceData(ref:ReferenceID; var data:univ ReferenceData); { defaults to -1 if not found }
- procedure GetReferenceDataPtr(ref:ReferenceID; var data:univ ReferenceData); { defaults to nil if not found }
- procedure SetReferenceData(ref:ReferenceID; data:univ ReferenceData);
-
- {
- References thast have not been used/accessed in over five minutes are deleted
- Reference IDs will almost never be resused
- MakeNewReference must not be called at interupt time, and make take some time (<1 tick), and may allocate memory
- Get/SetReferenceData/DataPtr can be called at interupt time, but requires A5 valid, and are very fast
- }
-
- implementation
-
- uses
- Events, LowMem, MyMemory, MyStartup;
-
- const
- minimum_life_time = 5*60{*60};
- const
- entries_array_bits = 6;
- entries_array_array_bits = 6;
- unique_bits = 32 - entries_array_array_bits - entries_array_bits;
- const
- entries_array_array_bit_pos = 32 - entries_array_array_bits;
- entries_array_bit_pos = entries_array_array_bit_pos - entries_array_bits;
- unqiue_bit_pos = 0;
- const
- entries_array_array_count = longint(2)**entries_array_array_bits;
- entries_array_count = longint(2)**entries_array_bits;
- unique_count = longint(2)**unique_bits;
-
- type
- EntryRecord = record
- ref:ReferenceID;
- data:ReferenceData;
- last_access_time:longint;
- end;
- EntryArray = array[0..entries_array_count-1] of EntryRecord;
- EntryArrayPtr = ^EntryArray;
- EntryArrayArray = array[0..entries_array_array_count-1] of EntryArrayPtr;
-
- var
- arrayarray:EntryArrayArray;
-
- procedure SplitRef(ref:ReferenceID; var i, j, unique:longint);
- begin
- i := BAND(BSR(ref, entries_array_array_bit_pos),entries_array_array_count-1);
- j := BAND(BSR(ref, entries_array_bit_pos),entries_array_count-1);
- unique := BAND(BSR(ref, unqiue_bit_pos),unique_count-1);
- end;
-
- procedure JoinRef(i, j, unique:longint; var ref:ReferenceID);
- begin
- ref := BSL(i, entries_array_array_bit_pos) + BSL(j, entries_array_bit_pos) + BSL(unique, unqiue_bit_pos);
- end;
-
- procedure MakeNewReference(var ref:ReferenceID; data:univ ReferenceData);
- var
- index_i, index_j, i, j, unique, time_minus_5, best_time, current_time:longint;
- begin
- ref := nil_reference;
- current_time := LMGetTicks;
- time_minus_5 := current_time - minimum_life_time;
- best_time := time_minus_5;
- index_i := -1;
- while index_i < 0 do begin
- for i := 0 to entries_array_array_count - 1 do begin
- if arrayarray[i] = nil then begin
- leave;
- end;
- for j := 0 to entries_array_count - 1 do begin
- if arrayarray[i]^[j].last_access_time < best_time then begin
- best_time := arrayarray[i]^[j].last_access_time;
- index_i := i;
- index_j := j;
- end;
- end;
- end;
- if index_i < 0 then begin
- for i := 0 to entries_array_array_count - 1 do begin
- if arrayarray[i] = nil then begin
- index_i := i;
- leave;
- end;
- end;
- if index_i >= 0 then begin
- if MNewPtr(arrayarray[i], SizeOf(EntryArray)) <> noErr then begin
- index_i := -1;
- end else begin
- for j := 0 to entries_array_count - 1 do begin
- arrayarray[index_i]^[j].ref := nil_reference;
- arrayarray[index_i]^[j].last_access_time := time_minus_5 - 1;
- end;
- index_j := 0;
- end;
- end;
- if index_i < 0 then begin
- best_time := current_time + 1; { this is not good, but is pratcially impossible }
- end;
- end;
- end;
- ref := arrayarray[index_i]^[index_j].ref;
- if ref = nil_reference then begin
- unique := 1;
- end else begin
- SplitRef(ref, i, j, unique);
- if unique = unique_count - 1 then begin
- unique := 1;
- end else begin
- unique := unique + 1;
- end;
- end;
- JoinRef(index_i, index_j, unique, ref);
- arrayarray[index_i]^[index_j].ref := ref;
- arrayarray[index_i]^[index_j].data := data;
- arrayarray[index_i]^[index_j].last_access_time := current_time;
- end;
-
- function ValidReference(ref:ReferenceID; var i, j, unique:longint):Boolean;
- begin
- ValidReference := false;
- if ref <> nil_reference then begin
- SplitRef(ref, i, j, unique);
- if (0 <= i) & (i < entries_array_array_count) & (arrayarray[i] <> nil) then begin
- if (0 <= j) & (j < entries_array_count) & (arrayarray[i]^[j].ref = ref) then begin
- arrayarray[i]^[j].last_access_time := LMGetTicks;
- ValidReference := true;
- end;
- end;
- end;
- end;
-
- function GetReferenceInfo(ref:ReferenceID; var data:univ ReferenceData):Boolean;
- var
- i, j, unique:longint;
- begin
- GetReferenceInfo := false;
- data := 0;
- if ValidReference(ref, i, j, unique) then begin
- data := arrayarray[i]^[j].data;
- end;
- end;
-
- procedure GetReferenceData(ref:ReferenceID; var data:univ ReferenceData); { defaults to -1 if not found }
- var
- i, j, unique:longint;
- begin
- data := -1;
- if ValidReference(ref, i, j, unique) then begin
- data := arrayarray[i]^[j].data;
- end;
- end;
-
- procedure GetReferenceDataPtr(ref:ReferenceID; var data:univ ReferenceData); { defaults to nil if not found }
- var
- i, j, unique:longint;
- begin
- data := 0;
- if ValidReference(ref, i, j, unique) then begin
- data := arrayarray[i]^[j].data;
- end;
- end;
-
- procedure SetReferenceData(ref:ReferenceID; data:univ ReferenceData);
- var
- i, j, unique:longint;
- begin
- if ValidReference(ref, i, j, unique) then begin
- arrayarray[i]^[j].data := data;
- end;
- end;
-
- procedure StartupReferences;
- var
- i:longint;
- begin
- for i := 0 to entries_array_array_count - 1 do begin
- arrayarray[i] := nil;
- end;
- end;
-
- end.
-